import React from 'react';
import PropTypes from 'prop-types';
import { Modal, Form, Input, Radio, Select, Button, message } from 'antd';
import _ from 'lodash';
import { IP_RE, CIDR_RE, PORT_RE, NAME_RE } from '@util/constants';
import H3CIcon from '../../images/h3cIcon.svg';
import CiscoIcon from '../../images/cisco.png';
import HuaweiIcon from '../../images/huawei.png';
import CheckIcon from '../../images/check.svg';
import './index.less';
import { connect } from 'react-redux';
import { addSwitch, editSwitch } from '@api/switch';
import { checkSwitch } from '@api/switch';
import SuccessIcon from '../../images/success.svg';
import FailIcon from '../../images/fail.svg';
import cn from 'classnames';

const { Option } = Select;

const formItemLayout = {
  labelCol: {
    span: 5
  },
  wrapperCol: {
    span: 19
  }
};
const intervalRegMaps = {
  minute: { reg: /^([3-5][0-9]|60)$/, max: 60, min: 30 },
  hour: { reg: /^(([1-9])|(1\d)|(2[0-4]))$/, max: 24, min: 1 },
  day: { reg: /^[1-9]\d{0,}$/, max: null, min: 1 }
};

class SwitchConfigModal extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      interval: intervalRegMaps['minute'],
      checking: false,
      checkResult: {},
      confirmLoading: false,
      id: _.get(props.data, '_id', ''),
      checkModalVisible: false
    };
    this.checkTime = 0;
  }

  componentDidUpdate(prevProps) {
    const preVisible = prevProps.visible;

    if (!preVisible && this.props.visible) {
      if (_.isEmpty(this.props.data)) {
        this.resetFields();
      } else {
        this.props.form.setFieldsValue(this.props.data);
        this.setState({
          interval: intervalRegMaps[_.get(this.props.data, 'interval.unit', 'minute')]
        });
      }

      this.setState({
        id: _.get(this.props.data, '_id', ''),
        checking: false,
        checkResult: {},
        confirmLoading: false
      });
    }
    if (preVisible !== this.props.visible) {
      this.checkTime = 0;
    }
  }

  onProtocalChange = e => {
    const value = e.target.value;
    const setFieldsValue = this.props.form.setFieldsValue;
    if (value === 'telnet') {
      setFieldsValue({ port: 23 });
    } else if (value === 'ssh') {
      setFieldsValue({ port: 22 });
    } else if (value === 'snmp') {
      setFieldsValue({ port: 161 });
    }
  };

  onIntervalUnitSelect = value => {
    this.setState({
      interval: intervalRegMaps[value]
    });
  };

  setIntervalValue = () => {
    const interval = this.state.interval;
    const { getFieldValue, setFieldsValue } = this.props.form;
    if (getFieldValue('interval.value') > interval.max) {
      setFieldsValue({ 'interval.value': interval.max });
    } else {
      setFieldsValue({ 'interval.value': interval.min });
    }
  };

  onIntervalInputBlur = () => {
    const interval = this.state.interval;
    const { getFieldValue } = this.props.form;
    if (!interval.reg.test(getFieldValue('interval.value'))) {
      this.setIntervalValue();
    }
  };

  resetFields = () => {
    this.props.form.resetFields();
    this.setState({
      id: '',
      interval: intervalRegMaps['minute']
    });
  };

  onSubmit = (toContinue = false) => {
    const id = this.state.id;
    const { validateFields } = this.props.form;
    validateFields((err, values) => {
      if (err) {
        return;
      }
      values.name = values.name.replace(/\s/g, '');

      let todo, tip;
      if (!id) {
        todo = addSwitch;
        tip = '添加';
      } else {
        values.id = id;
        todo = editSwitch;
        tip = '编辑';
      }

      this.setState({ confirmLoading: true });
      todo(_.pickBy(values, Boolean))
        .then(() => {
          message.success(`${tip}成功`);
          const updateBody = {
            confirmLoading: false
          };
          if (toContinue) {
            updateBody.checkResult = {};
          }
          this.setState(updateBody);
          this.props.afterSubmit(toContinue);
          if (toContinue) {
            this.resetFields();
          }
        })
        .catch(res => {
          let msg = '';
          if (_.get(res, 'message', '') === 'Same IP exists') {
            msg = ',交换机IP已存在';
          }
          if (_.get(res, 'message', '') === 'Same name exists') {
            msg = ',交换机名称重复';
          }
          message.error(`${tip}失败${msg}`);
          this.setState({
            confirmLoading: false,
            checkResult: {}
          });
        });
    });
  };

  onCheckSwitch = () => {
    const validateFields = this.props.form.validateFields;
    validateFields((err, rawValues) => {
      if (err) {
        return;
      }
      let values = _.clone(rawValues);
      values.name = values.name.replace(/\s/g, '');

      this.setState({
        checking: true,
        checkResult: {}
      });
      const checkTime = (this.checkTime = Date.now());
      checkSwitch(values)
        .then(res => {
          if (checkTime !== this.checkTime) {
            return;
          }
          const success = Boolean(_.get(res, 'data.data.reachable'));
          const updateBody = {
            checking: false,
            checkResult: {
              success,
              msg: success ? '连接成功!' : _.get(res, 'data.data.connection_fail', '连接失败!')
            },
            checkModalVisible: true
          };
          this.setState(updateBody);
        })
        .catch(err => {
          if (checkTime !== this.checkTime) {
            return;
          }
          this.setState({
            checking: false,
            checkResult: {
              success: false,
              msg: _.get(err, 'message', '连接失败!')
            },
            checkModalVisible: true
          });
        });
    });
  };

  render() {
    const { onClose } = this.props;
    const { getFieldDecorator, getFieldValue } = this.props.form;
    const { interval, checking, checkResult, confirmLoading, id, checkModalVisible } = this.state;
    const { visible } = this.props;

    const intervalSelect = getFieldDecorator('interval.unit', {
      initialValue: 'minute'
    })(
      <Select
        onSelect={value => this.onIntervalUnitSelect(value)}
        onBlur={() => {
          if (!interval.reg.test(getFieldValue('interval.value'))) {
            this.setIntervalValue();
          }
        }}
        style={{ width: 72 }}
      >
        <Option value="minute">分钟</Option>
        <Option value="hour">小时</Option>
        <Option value="day">天</Option>
      </Select>
    );
    const isSnmp = getFieldValue('protocal') === 'snmp';
    return (
      <>
        <Modal
          maskClosable={false}
          title={id ? '编辑交换机' : '添加交换机'}
          className="switch-config-modal"
          visible={visible}
          onCancel={onClose}
          footer={[
            <Button onClick={onClose} key="cancel">
              取消
            </Button>,
            <Button loading={checking} onClick={this.onCheckSwitch} key="check">
              验证连接
            </Button>,
            <Button
              type="primary"
              loading={!checkModalVisible && confirmLoading}
              onClick={() => this.onSubmit(false)}
              key="ok"
            >
              确定
            </Button>
          ]}
        >
          <Form {...formItemLayout} colon={false}>
            <Form.Item label="交换机名称">
              {getFieldDecorator('name', {
                rules: [
                  {
                    required: true,
                    message: '交换机名称不能为空'
                  },
                  {
                    pattern: NAME_RE,
                    message: '您输入的格式有误，仅支持中文、英文、数字、特殊字符 - 、— \\ _ / ：~'
                  },
                  {
                    max: 32,
                    message: '您输入的内容超过32个字符限制'
                  }
                ]
              })(<Input placeholder="请输入中文、英文、特殊字符或数字，不超过32个字符" />)}
            </Form.Item>
            <Form.Item label="交换机 IP">
              {getFieldDecorator('ip', {
                rules: [
                  {
                    required: true,
                    message: '交换机 IP 不能为空'
                  },
                  {
                    pattern: IP_RE,
                    message: '请输入正确格式的 IP 地址'
                  }
                ]
              })(<Input placeholder="如：10.0.12.21" />)}
            </Form.Item>
            <Form.Item label="协议">
              {getFieldDecorator('protocal', {
                initialValue: 'telnet'
              })(
                <Radio.Group onChange={this.onProtocalChange}>
                  <Radio value="telnet">telnet</Radio>
                  <Radio value="ssh">ssh</Radio>
                  <Radio value="snmp">snmp</Radio>
                </Radio.Group>
              )}
            </Form.Item>
            <Form.Item label="端口">
              {getFieldDecorator('port', {
                rules: [
                  {
                    required: true,
                    message: '端口不能为空'
                  },
                  {
                    pattern: PORT_RE,
                    message: '请输入正确格式的端口'
                  }
                ],
                initialValue: 23
              })(<Input style={{ width: 64 }} />)}
            </Form.Item>
            <Form.Item label="厂商">
              {getFieldDecorator('manufacturer', {
                initialValue: 'h3c'
              })(
                <Radio.Group className="manufacturers">
                  <Radio value="h3c">
                    <div className="manufacturer-icon">
                      <img src={H3CIcon} />
                      <div className="manufacturer-active">
                        <img src={CheckIcon} />
                      </div>
                    </div>
                    &nbsp;新华三
                  </Radio>
                  <Radio value="cisco">
                    <div className="manufacturer-icon">
                      <img src={CiscoIcon} />
                      <div className="manufacturer-active">
                        <img src={CheckIcon} />
                      </div>
                    </div>
                    &nbsp;思科
                  </Radio>
                  <Radio value="huawei">
                    <div className="manufacturer-icon">
                      <img src={HuaweiIcon} />
                      <div className="manufacturer-active">
                        <img src={CheckIcon} />
                      </div>
                    </div>
                    &nbsp;华为
                  </Radio>
                </Radio.Group>
              )}
            </Form.Item>
            <Form.Item label="获取周期">
              {getFieldDecorator('interval.value', {
                rules: [
                  {
                    required: true,
                    message: '获取周期不能为空'
                  },
                  { pattern: interval.reg, message: '请输入规定范围内的时间' }
                ],
                initialValue: 30
              })(
                <Input
                  style={{ width: 120 }}
                  addonAfter={intervalSelect}
                  onBlur={this.onIntervalInputBlur}
                />
              )}
            </Form.Item>
            <Form.Item label="所在网段">
              {getFieldDecorator('subnet', {
                rules: [
                  {
                    pattern: CIDR_RE,
                    message: '请输入正确格式的网段地址'
                  }
                ]
              })(<Input placeholder="如：10.10.10.0/24" />)}
            </Form.Item>
            {
              <Form.Item label="community">
                {getFieldDecorator('community', {
                  initialValue: 'public',
                  rules: [
                    {
                      required: isSnmp,
                      message: 'community不能为空'
                    }
                  ]
                })(<Input placeholder="请输入community" />)}
              </Form.Item>
            }
            <Form.Item label="管理员账号">
              {getFieldDecorator('username', {
                rules: [
                  {
                    required: !isSnmp,
                    message: '管理员账号不能为空'
                  }
                ]
              })(<Input placeholder="请输入账号" />)}
            </Form.Item>
            <Form.Item label="管理员密码" style={{ marginBottom: 0 }}>
              {getFieldDecorator('password', {
                rules: [
                  {
                    required: !isSnmp,
                    message: '管理员密码不能为空'
                  }
                ]
              })(<Input.Password placeholder="请输入密码" />)}
            </Form.Item>
          </Form>
        </Modal>
        <Modal
          maskClosable={false}
          visible={checkModalVisible}
          className={cn(
            'no-header-bottom-lines',
            'bottom-center',
            'padding-24',
            'switch-config-check-switchc-modal'
          )}
          onCancel={() => this.setState({ checkModalVisible: false })}
          footer={[
            <Button onClick={() => this.setState({ checkModalVisible: false })} key="return">
              返回修改
            </Button>,
            <Button
              type="primary"
              onClick={() => this.setState({ checkModalVisible: false }, this.onSubmit(true))}
              loading={confirmLoading}
              key="continue"
            >
              继续添加
            </Button>
          ]}
        >
          <div>
            <img src={checkResult.success ? SuccessIcon : FailIcon} />
            <div className="check-status">{checkResult.success ? '连接成功' : '连接失败'}</div>
            {!checkResult.success && checkResult.msg && (
              <div className="check-msg">{checkResult.msg}</div>
            )}
          </div>
        </Modal>
      </>
    );
  }
}

SwitchConfigModal.propTypes = {
  form: PropTypes.object,
  onClose: PropTypes.func,
  visible: PropTypes.bool,
  afterSubmit: PropTypes.func,
  confirmLoading: PropTypes.bool,
  data: PropTypes.object
};

const mapStateToProps = state => {
  return {
    socketIO: _.get(state, 'socketIO.socketIO', null)
  };
};

export default connect(mapStateToProps)(Form.create()(SwitchConfigModal));
